package file.handle.impl;

import file.constant.SysConstant;
import file.handle.FileHandle;
import file.model.FileModel;
import file.model.FileTransferModel;
import file.untils.FileUntils;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * @Author: zou
 * @email: 704572528@qq.com
 * @Date: 2020/10/27 21:22
 */
public class FileHandleImpl implements FileHandle {
    /**
     * 文件夹复制
     */
    private static List<FileTransferModel> copyInput;

    /**
     * 默认生成.txt文件
     *
     * @param fileModel
     * @return
     */
    @Override
    public Boolean createFile(FileModel fileModel) {

        String path = fileModel.getPath() + "\\" + String.format(SysConstant.DEFAULT_FILE_NAME, 0);
        // 获取是否存在的文件
        File file = existFile(path, SysConstant.DEFAULT_FILE_NAME);
        try {
            file.createNewFile();
        } catch (IOException e) {
            return false;
        }
        return true;
    }

    /**
     * 创建文件夹
     *
     * @param fileModel
     * @return
     */
    @Override
    public Boolean createFolder(FileModel fileModel) {
        String path = fileModel.getPath() + "\\" + String.format(SysConstant.DEFAULT_FILE_FOLDER, 0);
        // 获取是否存在的文件
        File file = existFile(path, SysConstant.DEFAULT_FILE_FOLDER);
        // 创建文件夹
        try {
            file.mkdirs();
        } catch (Exception e) {
            return false;
        }

        return true;
    }

    /**
     * 修改文件名字
     *
     * @param originalFile 原文件
     * @param newFile      新文件
     * @return
     */
    @Override
    public Boolean changeFileName(FileModel originalFile, FileModel newFile) {

        File file = new File(originalFile.getPath());
        if (file != null) {
            // 新文件
            File file1 = new File(newFile.getPath());
            if (!file1.exists()) {
                file.renameTo(file1);
            }
        }
        return true;
    }

    /**
     * 递归找到不存在的文件名为止
     *
     * @param path
     */
    private File existFile(String path, String defaultName) {
        File file = this.getFile(path);
        if (file.exists()) {
            // 随机10以内的数
            String format = String.format(defaultName, new Random().nextInt(10));
            int i = path.lastIndexOf("\\");
            if (i != -1) {
                path = path.substring(0, i) + "\\" + format;
            }
            file = this.getFile(path);
            this.existFile(path, defaultName);
        }
        return file;
    }


    /**
     * 粘贴操作
     *
     * @param fileModel
     * @param toPath    复制到那个路径下
     * @return
     */
    @Override
    public Boolean copyFile(FileModel fileModel, String toPath) {
        if (copyInput == null || copyInput.size() == 0 || toPath.isEmpty()) {
            return false;
        }
        // 复制流
        copyInputFile(toPath);

        return true;
    }

    /**
     * 使用复制流
     *
     * @param toPath
     */
    private void copyInputFile(String toPath) {
        // 复制到这个目录下
        File file = this.getFile(toPath);
        // 不存在
        if (!file.exists()) {
            // 创一个目录
            file.mkdirs();
        }
        FileModel fm = null;
        OutputStream os;
        InputStream io;
        int len;
        byte[] b = new byte[1024];
        // 遍历复制流
        try {
            for (FileTransferModel ftm : copyInput) {
                fm = ftm.getFileModel();
                io = ftm.getIo();
                // 是文件夹的话 创建文件夹即可
                if (fm.getFolder()) {
                    toPath = toPath + "\\" + fm.getName();
                    file = new File(toPath);
                    if (!file.exists()) {
                        file.mkdirs();
                    }
                } else {
                    // 文件的话
                    toPath = toPath + "\\" + fm.getName();
                    os = new BufferedOutputStream(new FileOutputStream(toPath));
                    while ((len = io.read(b)) != -1) {
                        // 写出数据
                        os.write(b, 0, len);
                    }

                    //关闭资源
                    io.close();
                    os.close();
                }
                // 剪切的话把原来的文件删除
                if (ftm.getShear()) {
                    removeFile(this.getFile(fm.getPath()));
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 清空复制流
        copyInput = null;
    }


    /**
     * 剪切的后期处理
     *
     * @param fm
     * @param fd
     */
    private void shearHadele(FileTransferModel fm, FileModel fd) {
        if (fm.getShear()) {
            this.removeFile(fd.getPath());
        }
    }


    /**
     * 读到内存里
     *
     * @param fileModel
     * @return
     */
    @Override
    public List<FileTransferModel> inputFile(String fileModel) {

        copyInput = this.listCopyInput(fileModel, false);

        return copyInput;
    }

    /**
     * 把所有缓冲路存起来
     *
     * @param pathAndName
     * @param isShear
     * @return
     */
    private List<FileTransferModel> listCopyInput(String pathAndName, boolean isShear) {

        List<FileTransferModel> streamList = new ArrayList<>();
        if (pathAndName != null) {
            // 文件读取
            fileInput(pathAndName, streamList, isShear);
        }
        return streamList;
    }

    /**
     * 读取文件到流中
     *
     * @param pathAndName
     * @param streamList
     * @param isShear
     */
    private void fileInput(String pathAndName, List<FileTransferModel> streamList, boolean isShear) {

        File file = getFile(pathAndName);
        if (file != null) {
            // 如果是一个文件
            if (file.isFile()) {
                InputStream io = this.getInputStream(streamList, file);
                setFileList(io, streamList, file, isShear);
            } else {
                // 文件夹 输入流 不用 因为只记录 文件名
                setFileList(null, streamList, file, isShear);
                File[] files = file.listFiles();
                if (files != null) {
                    // 递归记录文件名
                    for (File file1 : files) {
                        fileInput(file1.getPath(), streamList, isShear);
                    }
                }
            }
        }
    }

    @Override
    public Boolean removeFile(String pathAndName) {

        File file = getFile(pathAndName);
        if (file != null) {
            // 删除还是复制
            removeFile(file);
        }

        return true;
    }

    /**
     * 删除文件
     *
     * @param file
     */
    private void removeFile(File file) {
        // 文件
        if (file.isFile()) {
            file.delete();
        } else {
            // 文件夹
            File[] files = file.listFiles();
            if (files != null) {
                for (File file1 : files) {
                    // 递归删除
                    removeFile(file1);
                }
            }
            // 把目录下的文件删完 文件夹也删除
            file.delete();
        }
    }

    /**
     * 剪切文件
     *
     * @param path
     */
    @Override
    public void shearFile(String path) {
        if (path.isEmpty()) {
            return;
        }
        boolean isShear = true;
        copyInput = this.listCopyInput(path, isShear);

    }

    /**
     * 文件删除还是
     *
     * @param files
     * @param isRemove   true 删除 false 复制
     * @param streamList
     * @param isShear
     */
    private void folderRemonveOrCopy(File files, boolean isRemove, List<FileTransferModel> streamList, boolean isShear) {

        if (files != null) {
            InputStream io = null;
            if (files.isFile()) {
                if (isRemove) {
                    files.delete();
                } else {
                    // 复制的话
                    // getInputStream(streamList, io, files, isShear);
                }
                return;
            } else {
                // 处理文件夹
                folderHandle(files, isRemove, streamList, isShear);
            }
        }
    }

    /**
     * 文件夹处理
     *
     * @param files
     * @param isRemove
     * @param streamList
     * @param isShear
     */
    private void folderHandle(File files, boolean isRemove, List<FileTransferModel> streamList, boolean isShear) {
        InputStream io = null;
        if (files.isDirectory()) {
            if (isRemove) {
                files.delete();
            }
            File[] files1 = files.listFiles();
            if (files1 != null) {
                for (File file : files.listFiles()) {
                    // 是文件的情况下
                    if (file.isFile()) {
                        if (isRemove) {
                            file.delete();
                        } else {
                            // io = getInputStream(streamList, io, file, isShear);
                        }
                    } else {
                        if (!isRemove) {
                            // setFileList(null, streamList, isShear, file);
                        } else {
                            file.delete();
                        }
                        folderHandle(file, isRemove, streamList, isShear);
                    }
                }
            }
        } else {
            if (isRemove) {
                files.delete();
            }
        }


    }

    /**
     * 加入流
     *
     * @param io
     * @param streamList
     * @param file
     * @param isShear
     */
    private void setFileList(InputStream io, List<FileTransferModel> streamList, File file, boolean isShear) {
        FileTransferModel fm = new FileTransferModel(io, FileUntils.getFileModel(file));
        fm.setShear(isShear);
        // 文件夹直接加入
        streamList.add(fm);
    }

    /**
     * 获取输入流
     *
     * @param streamList
     * @param io
     * @param file
     * @param isShear
     * @return
     */
    private InputStream getInputStream(List<FileTransferModel> streamList, File file) {
        InputStream io = null;
        try {
            io = new BufferedInputStream(new FileInputStream(this.getFile(file.getAbsolutePath())));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        // setFileList(io, streamList, isShear, file);
        return io;
    }


    /**
     * 获取文件
     *
     * @param path
     * @return
     */
    private File getFile(String path) {
        return new File(path);
    }
}
